#include <math.h>
#include <iostream>
#include <functional>

using namespace std;

//抽象类
class Figure
{
public:
    //给两个类型起别名
    //一个类型是function<void()>
    //另一个类型是function<double()>
    using Display = function<void()>;
    using Area = function<double()>;

    void setDisplay(Display && con){
        _display = std::move(con);
    }
    void setArea(Area && con){
        _area = std::move(con);
    }

    void handleDisplay()const
    {
        if(_display){
            _display();
        }
    }
    double hanleArea()const
    {
        if(_area){
           return  _area();
        }
        else{
              return 0.0;
        }
    }
    //任何一个类型都可以创建对象、变量
    //两个类型分别创建对象，这两个对象都是Figure的数据成员
    Display _display;
    Area _area;
};

class Rectangle
{
public:
    Rectangle(double len = 0, double width = 0)
    : _len(len)
    , _width(width)
    {
        cout << "Rectangle(double = 0, double = 0)" << endl;
    }

    void display() const 
    {
        cout << "Rectangle";
    }

    double area() const 
    {
        return _len * _width;
    }

    ~Rectangle()
    {
        cout << "~Rectangle()" << endl;
    }

private:
    double _len;
    double _width;

};

//Circle c1 = 10;//int ===>Circle
class Circle
{
public:
    explicit
    Circle(double radius = 0)
    : _radius(radius)
    {
        cout << "Circle(double = 0)" << endl;
    }

    void display() const 
    {
        cout << "Circle";
    }

    double area() const 
    {
        return 3.14 * _radius * _radius;
    }

    ~Circle()
    {
        cout << "~Circle()" << endl;
    }
private:
    double _radius;
};

class Triangle
{
public:
    Triangle(double a = 0, double b = 0, double c = 0)
    : _a(a)
    , _b(b)
    , _c(c)
    {
        cout << "Triangle(double = 0, double = 0, double = 0)" << endl;
    }

    void display() const 
    {
        cout << "Triangle" ;
    }

    double area() const 
    {
        double tmp = (_a + _b + _c)/2;
        return sqrt(tmp * (tmp - _a) * (tmp - _b) * (tmp -_c));
    }

    ~Triangle()
    {
        cout <<"~Triangle()" << endl;
    }
private:
    double _a;
    double _b;
    double _c;
};

void func(const Figure &ref)
{
    ref.handleDisplay();
    cout << "'s 的面积 " << ref.hanleArea() << endl;
}

int main(int argc, char **argv)
{
    Rectangle rec(10, 20);
    Circle cir(10);
    Triangle tri(3, 4, 5);

    Figure fig;

    fig.setDisplay(bind(&Rectangle::display,&rec));
    fig.setArea(bind(&Rectangle::area,&rec));
    func(fig);

    fig.setDisplay(bind(&Circle::display,&cir));
    fig.setArea(bind(&Circle::area,&cir));
    func(fig);
    
    fig.setDisplay(bind(&Triangle::display,&tri));
    fig.setArea(bind(&Triangle::area,&tri));
    func(fig);

    return 0;
}



